extern crate chrono;
use chrono::prelude::*;
use std::collections::*;

/**
 * 函数的基本形式
 * fn <函数名> ( <参数> ) <函数体>
 */

fn add(x: i32, y: i32) -> i32 { 
    x + y 
}

fn sub(x: i32, y: i32) -> i32 { 
    x - y 
}

fn div(x: i32, y: i32) -> i32 {
    x / y
}

fn mul(x: i32, y: i32) -> i32 { 
    x * y 
}

// rust不用显式return
fn operate(x: i32, y: i32, f: fn(i32, i32) -> i32) -> i32 {
    f(x, y)
}

fn str_func(str: String) -> fn(i32, i32) -> i32 {
    match str.as_str() { 
        "+"         => add,
        "-"         => sub,
        "*"         => mul,
        "/"         => div,
        _           => add
    }
}


fn test_operate() -> () {
    let xf = String::from("+");
    let x1 = operate(1, 2, str_func(xf));
    println!("({} + {}) = {}", 1, 2, x1);
    let x2 = operate(2, 3, sub);
    println!("({} - {}) = {}", 1, 2, x2);
}


// --------------------------------------------

// 无申明，默认最后一行 无; 则为返回值，加了; 即无返回值
fn pi() -> f64 {
    3.141592653589793238
}

// 可以显示申明return
fn pi_show() -> f64 {  
    return pi() 
}

fn pi_none() {
    3.141592653589793238;
}

fn pi_none1() -> () {
    3.141592653589793238;
}


fn test_fun_return() {
    let pai: f64 = pi_show();
    println!("{}", pai);
    let xx: () = pi_none();
    let xx1: () = pi_none1();
}

// --------------------------------------------
// 性别枚举
enum Sex {
    None    = 0,    // 未知的
    Man     = 1,    // 男
    Woman   = 2,    // 女
}

struct User {
    id: i64,        // 用户id
    name: String,   // 用户名称
    sex: Sex,       // 性别
}

struct UserTopic {
    id:     i64,    // 用户队列id
    name:   String, // 用户队列名称
    owner:  i64,    // 用户id
}

enum MessageType { 
    None        = 0, // 未知
    Text        = 1, // 文本
    Emoji       = 2, // 表情
    RedEnvelope = 3, // 红包
    Image       = 4, // 图片
 }

/**
 * 元组结构体
 * 没有字段名称，通过 . 和下标来进行访问：
 */
struct Message(MessageType, String);

// Event：标准的标签联合体，它定义了三种事件：Join、Leave、Message。每种事件都有自己的数据结构。
enum Event{
    // 元组结构体
    Join(i64, i64),                 // i64[用户id], i64[topicid]
    Leave(i64, i64),                // i64[用户id], i64[topicid]
    SendMessage(i64, i64, Message), // i64[用户id], i64[topicid], Message[消息]
}

fn test_data_struct() {
    let user1 = User { id: 1, name: "user1".into(), sex: Sex::Man };
    let user1_topic = UserTopic { id: 1, name: "/chat/user1/topic".into(), owner: user1.id };

    let user2 = User { id: 2, name: "user2".into(), sex: Sex::Woman };
    let user2_topic = UserTopic { id: 2, name: "/chat/user2/topic".into(), owner: user2.id };

    let event1 = Event::Join(user1.id, user1_topic.id);
    let event2 = Event::Join(user2.id, user2_topic.id);
    // 发给 user1 一条消息的事件
    let event3 = Event::SendMessage(user1.id, user1_topic.id, Message(MessageType::Text, "hello rust!".into()));
}

// --------------------------------------------

// -----------------值得生杀大权-----------------
fn index_of(data: Vec<u32>, v: u32) -> Option<usize> {
    for (index, x) in data.iter().enumerate() {
        if *x == v {
            return Some(index)
        }
    }

    None
}

fn test_index_of() -> () {
    let data = vec![1, 2, 3, 4, 5, 6];
    let v = 5;
    match index_of(data, v) {
        Some(pos)   =>  println!("find success {}", pos),
        _           =>  println!("not found")
    }
}
// --------------------------------------------

// ---------------打印三角形---------------------
fn str_repeat(str_ele: &str, count: u32) -> String {
    // let mut r = String::from("");
    // for i in 0..count {
    //     r.push_str(str);
    // }

    // r
    // fn concat<'a>(s1: String, s2: &str) -> String {
    //     return s1 + s2;
    // };

    (0..count).map(|x| -> &str {str_ele}).fold(String::from(""), |s1, s2| -> String {s1 + s2})
}

#[derive(PartialEq)]
enum Sort {
    ASC     = 0,
    DESC    = 1,
}

fn print_triangle(len: u32, sort: Sort) -> () {
    for i in 0..len {
        let cal_str = if sort == Sort::ASC {
            format!("{}{}", str_repeat(" ", len - i), str_repeat("*", 2*i+1))
        } else {
            format!("{}{}", str_repeat(" ", i), str_repeat("*", 2*(len - i)+1))
        };
        println!("{}", cal_str);
    }
}
// --------------------------------------------

// ---------------&str和String的区别-------------
fn diff_string() -> () {
    // 只有 String + &str -> String 这样的拼接 才是对的
    // let string1 = "123";
    // let string2 = string1;
    // // 编译报错 value borrowed here after move。String 没有实现 copy语义
    // println!("{}", string1);
    let str1: &str = "123";
    let str2 = str1;
    // 正常运行，因为 &str实现了copy语义
    println!("{}", str1);
}
// ---------------------------------------------

// ---------------
fn div_test() -> () {
    let x: i32 = 1;
    let y: i32 = 2;
    println!("{}", x/y);
    println !("{}", x as f32 / y as f32);
}
// ---------------

// ---------------
fn test_array() -> () {
    // array 长度不可变
    let arr1 = [1, 2, 3, 4, 5];
    let arr2:[i32;5] = [1, 2, 3, 4, 5];
    // Vector长度可变
    let mut arr3: Vec<i32> = vec![1, 2, 3, 4, 5];
    arr3.push(6);
    println!("vec: {:?}", arr3);
}
// ---------------


// ---------------
fn test_tuple() -> () {
    let tup4: (&str, String, i32, f64) = ("123" , String::from("123"), 123, 123.0);
    println!("{}", tup4.0);
}
// ---------------

// ---------------
fn print_current_month() -> () {
    let mon_arr = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
    let curr_month = Local::today().month();
    // println!("{}", curr_month);
    // 数组的索引 必须是 usize 类型
    println!("现在是:{}", mon_arr[curr_month as usize]);
}
// ---------------

// ---------------
fn test_loop() -> () {
    let mon_arr = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
    for (i, e) in mon_arr.iter().enumerate() {
        println!("index={}, element={}", i, e);
    }

    let mon_arr_concat = mon_arr.iter().enumerate().fold(String::from(""), |r, e| -> String { r + "->" + e.0.to_string().as_str() + ":" + e.1 });
    println!("{}", mon_arr_concat);

    let join = |e1: String, e2: String| -> String {
        return format!("{}->{}", e1, &e2);
    };
    let convert = |x: &&str| -> String { (*x).to_string() };
    let mon_arr_concat1 = mon_arr.iter().map(convert).reduce(join);
    println!("{}", mon_arr_concat1.unwrap_or(String::from("")));
}
// ---------------

// ---------------
fn small_lest(x: i32, y: i32) -> i32 { 
    if x < y {x} else {y}
 }
// ---------------

fn odd(max: i32) -> Vec<i32> {
    (0..max).filter(|x| x%2 == 1).collect()
}

// ---------------
fn test_left_time() -> () {
    let see = |see_str: String| -> () {
        println!("{}", see_str);
    };
    // x1在栈上(起始位置、长度、容量) Hello World!在堆上
    let x1 = String::from("Hello World!");
    see(x1);
    // 编译报错，因为x1已经被see函数借走了所有权
    // println!("{}", x1);


    let x2 = String::from("Hello World!");
    let see1 = |see_str: &String| -> () {
        println!("{}", see_str);
    };
    // 传引用
    see1(&x2);
    println!("{}", x2);


    let mut x3: String = String::from("Hello World!");
    // 编译报错，因为see_str是不可变的引用
    // let fix1 = |see_str: &String| -> () {
    //     see_str.pop();
    // };
    // fix1(&x3);
    println!("{}", x3);
    // 可变引用
    let fix2 = |see_str: &mut String| -> () {
        see_str.pop();
    };
    fix2(&mut x3);
    println!("{}", x3);

}
// ---------------

// ---------------
fn test_array_slice() -> () {
    let xs = [1, 2, 3, 4, 5, 6, 7, 8];
    let see = |x: &[i32]| -> () { println!("{:?}", x); };
    // 切片 含头不含尾
    see(&xs[1..3]);
}
// ---------------

// ---------------
fn test_modify_array() -> () {
    let mut xs = vec![1, 2, 3, 4, 5, 6, 7,  8, 9, 10, 11, 12, 13];
    let mut xsx: Vec<String> = Vec::with_capacity(10);
    let fix = |v: &mut Vec<i32>| -> () { v.push(14); };
    fix(&mut xs);
    println!("{:?}", xs);
}
// ---------------

// ---------------
fn see_array() -> () {
    let xs = vec![1, 2, 3, 4, 5];
    println!("{}", xs[3]);
}
// ---------------

fn test_hash_map() -> () {
    let mut xs_map: HashMap<String, String> = HashMap::new();
    xs_map.insert(String::from("name"), String::from("yangxuan"));
    xs_map.insert(String::from("age"), String::from("18"));
    println!("{:?}", xs_map);
    let value = xs_map.get("name1")
        .map(|x| format!("vale:{}", x))
        .unwrap_or("nothing find".to_string());
    println!("{}", value);

    for x in xs_map.iter() {
        println!("{:?}", x);
        println!("key:{}, value:{}", x.0, x.1);
    }

    let mut xs_map1: HashMap<i32, String> = HashMap::new();
    xs_map1.insert(1, String::from("yangxuan"));
    xs_map1.insert(2, String::from("18"));
    let kkey = 2;
    let vv = xs_map1.get(&kkey).map(|x| x.to_string()).unwrap_or("nothing find".to_string());
    println!("{}", vv);
}

fn test_group() -> () {
    let xs_list = vec![("A", 1), ("B", 2), ("C", 3), ("D", 4), ("A", 2), ("B", 3)];
    // 这里 |y| y.0 == k 和 |y| *y.0 == *k 是等价的
    let find_key = |k: &str| -> Vec<&(&str, i32)> { xs_list.iter().filter(|y| y.0 == k).collect() };
    println!("vv:{:?}", find_key("A"));
}

fn main() {

    // // 测试四则运算
    // test_operate();

    // // 测试函数返回值
    // test_fun_return();

    // // 测试数据结构
    // test_data_struct();

    // test_index_of()

    // print_triangle(10, Sort::DESC);

    // div_test();

    // test_array();

    // test_tuple();

    // print_current_month();

    // test_loop();

    // println!("{}", small_lest(11, 22));
    
    // println!("{:?}", odd(100))

    // test_left_time();

    // test_array_slice();

    // test_modify_array();

    // see_array();

    // test_hash_map();

    test_group();
}
